package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.core.exception.BizException;
import com.eastfair.venueservice.dao.LoadInfoMapper;
import com.eastfair.venueservice.dto.LoadInfoDTO;
import com.eastfair.venueservice.dto.LoadInfoExamineDTO;
import com.eastfair.venueservice.dto.LoadInfoPageQuery;
import com.eastfair.venueservice.dto.LoadOrderDTO;
import com.eastfair.venueservice.entity.LoadInfo;
import com.eastfair.venueservice.enums.LogisticsExamineStateEnum;
import com.eastfair.venueservice.service.LoadInfoService;
import com.eastfair.venueservice.service.LogisticsOrderService;
import com.eastfair.venueservice.vo.LoadInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 智慧物流 装卸服务
 *
 * @author Du Xiaobo
 * @date 2023/5/8 14:19
 */
@Service
@Slf4j
public class LoadInfoServiceImpl extends SuperServiceImpl<LoadInfoMapper, LoadInfo> implements LoadInfoService {

    @Resource
    private LogisticsOrderService logisticsOrderService;

    @Override
    public Long saveLoadInfo(LoadInfoDTO dto) {
        log.info("新增装卸服务入参：dto={}", dto);
        LoadInfo info = new LoadInfo();
        BeanUtils.copyProperties(dto, info);
        info.setExamineState(LogisticsExamineStateEnum.APPLIED.getCode());
        // 计算服务费用
        BigDecimal estimatedServiceCost = calServiceCost(dto.getEstimateVolume(), dto.getServiceNumber(), dto.getServicePrice());
        info.setEstimatedServiceCost(estimatedServiceCost);
        // 计算租赁费用
        if (StringUtils.isNotEmpty(dto.getLeaseContent())) {
            BigDecimal estimatedLeaseCost = calLeaseCost(dto.getLeaseNumber(), dto.getLeasePrice());
            info.setEstimatedLeaseCost(estimatedLeaseCost);
        } else {
            info.setEstimatedLeaseCost(BigDecimal.ZERO);
        }
        // 判断与前端传来数值是否一致
        if (info.getEstimatedServiceCost().add(info.getEstimatedLeaseCost()).compareTo(dto.getTotalCost()) != 0) {
            throw BizException.wrap("预计费用计算有误");
        }
        save(info);
        log.info("新增装卸服务成功：model={}", info);
        return info.getId();
    }

    @Override
    public void updateLoadInfo(LoadInfoDTO dto) {
        log.info("修改装卸服务入参：dto={}", dto);
        LoadInfo one = lambdaQuery().eq(LoadInfo::getId, dto.getId()).one();
        if (Objects.isNull(one)) {
            throw BizException.wrap("修改的记录不存在");
        }
        LoadInfo info = new LoadInfo();
        BeanUtils.copyProperties(dto, info);
        updateById(info);
        log.info("修改装卸服务成功：model={}", info);
    }

    @Override
    public LoadInfoVo getLoadInfoById(Long id) {
        LoadInfo info = lambdaQuery().eq(LoadInfo::getId, id).one();
        if (Objects.isNull(info)) {
            throw BizException.wrap("查询记录不存在,id={}", id);
        }
        LoadInfoVo vo = new LoadInfoVo();
        BeanUtils.copyProperties(info, vo);
        return vo;
    }

    @Override
    public Page<LoadInfoVo> listLoadInfo(PageParams<LoadInfoPageQuery> pageParams) {
        log.info("listLoadInfo - 查询装卸服务列表VO, pageParams={}", pageParams);
        Page<LoadInfo> pageParam = pageParams.buildPage();
        QueryWrapper<LoadInfo> queryWrapper = createLoadInfoQueryWrapper(pageParams);
        Page<LoadInfo> page = page(pageParam, queryWrapper);
        Page<LoadInfoVo> voPage = new Page<>();
        BeanUtil.copyProperties(page, voPage);
        List<LoadInfo> list = page.getRecords();
        if (list == null || list.isEmpty()) {
            return voPage;
        }
        List<LoadInfoVo> voList = list
                .stream()
                .map(load -> BeanUtil.toBean(load, LoadInfoVo.class))
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public Boolean examine(LoadInfoExamineDTO dto) {
        log.info("examine - 装卸服务审核入参, dto={}", dto);
        LoadInfo model = lambdaQuery().eq(LoadInfo::getId, dto.getId()).one();
        if (Objects.isNull(model)) {
            throw BizException.wrap("查询记录不存在,id={}", dto.getId());
        }
        LogisticsExamineStateEnum stateEnum = LogisticsExamineStateEnum.valueOf(dto.getExamineState());

        //审核相关信息
        model.setExamineState(stateEnum.getCode());
        model.setExamineTime(LocalDateTime.now());
        model.setExamineReason(dto.getExamineReason());

        // 判断审核状态
        if (LogisticsExamineStateEnum.APPROVED.equals(stateEnum)) {

            model.setActualVolume(dto.getActualVolume());
            model.setActualLeaseNumber(dto.getActualLeaseNumber());
            model.setActualServiceNumber(dto.getActualServiceNumber());
            // 计算实际服务费用
            model.setActualServiceCost(calServiceCost(model.getActualVolume(), model.getServiceNumber(), model.getServicePrice()));
            // todo 计算租赁实际费用
            // todo 生成物流订单
            LoadOrderDTO loadOrder = new LoadOrderDTO();
            logisticsOrderService.saveLoadOrder(loadOrder);
            // todo 同步支付系统
        }
        updateById(model);
        log.info("examine - 装卸服务审核完成");
        return true;
    }

    /**
     * 服务费用计算
     *
     * @param volume 体积
     * @param number 数量
     * @param price  单价
     * @return
     */
    private BigDecimal calServiceCost(BigDecimal volume, Integer number, BigDecimal price) {
        return volume.multiply(price).multiply(BigDecimal.valueOf(number));
    }

    /**
     * 租赁费用计算
     *
     * @param number
     * @param price
     * @return
     */
    private BigDecimal calLeaseCost(Integer number, BigDecimal price) {
        return price.multiply(BigDecimal.valueOf(number));
    }

    private QueryWrapper<LoadInfo> createLoadInfoQueryWrapper(PageParams<LoadInfoPageQuery> params) {
        LoadInfoPageQuery model = params.getModel();
        QueryWrapper<LoadInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(StrUtil.isNotBlank(model.getExhibitionName()), LoadInfo::getExhibitionName, model.getExhibitionName())
                .eq(StrUtil.isNotBlank(model.getPrincipalType()), LoadInfo::getPrincipalType, model.getPrincipalType())
                .eq(StrUtil.isNotBlank(model.getServiceContent()), LoadInfo::getServiceContent, model.getServiceContent())
                .eq(StrUtil.isNotBlank(model.getLeaseContent()), LoadInfo::getLeaseContent, model.getLeaseContent())
                // 审核状态
                .eq(StrUtil.isNotBlank(model.getExamineState()), LoadInfo::getExamineState, LogisticsExamineStateEnum.valueOf(model.getExamineState()).getCode())
        ;
        if (StrUtil.isNotBlank(params.getOrder())) {
            if (StrUtil.isNotBlank(params.getOrder())) {
                queryWrapper.orderBy(false, "ASC".equals(params.getSort().toUpperCase()), params.getOrder());
            }
        }
        return queryWrapper;
    }
}
